﻿using System;
using System.Media;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using Rabbit.Model;
using System.Windows.Input;
using System.Windows.Threading;
using Rabbit.BusinessLogicLayer;
using Rabbit.Utils;
using Rabbit.Controls;
using System.Windows.Media;
namespace MicroBlogClient
{
    public abstract class PageBase : Page
    {
        public static UserSettings MySettings { get; set; }
        protected static SoundPlayer Player { get; set; }
        protected static readonly int MaxRecordsCountShowed = 20;
        private MainWindow mainWindow = App.Current.MainWindow as MainWindow;
        public PageBase()
        {
            MySettings = (App.Current.MainWindow as MainWindow).Me.UserSettings;
            Player = (App.Current.MainWindow as MainWindow).Player;
        }
         
        /// <summary>
        /// when the user click the UI updates in the main window, main window should call this
        /// method to update this pages data or UI
        /// </summary>
        public abstract void DoWork(object obj = null);
        /// <summary>
        /// if this page's status updated, it should notify the main window to do UI update
        /// </summary>
        protected abstract void NotifyMainWindowNewMessageCountChanged(int messageCount);

        public abstract void BeginInitializeMessage();


        #region Message Helper
        /// <summary>
        /// show processing message, this usually is called when a long-time run task started
        /// such as fetching data from the server
        /// </summary>
        /// <param name="message"></param>
        protected void ShowProcessingMessage(string message)
        {
            this.Dispatcher.BeginInvoke(new Action(() =>
                {
                    (App.Current.MainWindow as MainWindow).showProcessingMessage(message);
                }));
        }

        protected void ShowFailedMessage(string message)
        {
            this.Dispatcher.BeginInvoke(new Action(() =>
                {
                    (App.Current.MainWindow as MainWindow).showFailedMessage(message);
                }));
        }

        protected void ShowFailedMessage(MaxRatesExceededException ex)
        {
            this.Dispatcher.BeginInvoke(new Action(() =>
            {
                (App.Current.MainWindow as MainWindow).showFailedMessage("超过最大次数访问上限，该限制将在" + ex.RatesInformation.ResetTime + "后自动解除");
            }));
        }
        protected void ShowSuccessfulMessage(string message)
        {
            this.Dispatcher.BeginInvoke(new Action(() =>
                {
                    (App.Current.MainWindow as MainWindow).showSuccessfulMessage(message);
                }));
        }
        #endregion

        #region Status Operation Helper

        protected void ReplyStatusHandler(object sender, RoutedEventArgs e)
        {
            
            Hyperlink link = sender as Hyperlink;
            mainWindow.IsOperatingOrignalStatus = link.CommandParameter.ToString() == "1";
            mainWindow.CurrentOperatingStatus = Rabbit.Utils.Common.GetListBoxItemFromChild(link.Parent as DependencyObject).Content as Status;
            mainWindow.tbOperationType.Text = "评论";
            mainWindow.chkCommentOrignalStatus.Visibility = System.Windows.Visibility.Collapsed;
            mainWindow.IsReplyToStatus = true;
            mainWindow.IsReplyToComment = false;
            mainWindow.popupReplyOrForward.PlacementTarget = (UIElement)link.Parent;
            mainWindow.popupReplyOrForward.Placement = System.Windows.Controls.Primitives.PlacementMode.Bottom;
            mainWindow.popupReplyOrForward.IsOpen = true;
        }

        protected void AddStatusToFavoritesHandler(object sender, RoutedEventArgs e)
        {
            string statusID = ((Hyperlink)sender).CommandParameter.ToString();
            Action addToStatusHandler = () =>
                {
                    try
                    {
                        Status status = StatusesBL.AddStatusToFavorites(statusID);
                        //TODO add the new favorite to local client
                        ShowSuccessfulMessage("收藏成功");
                    }
                    catch (MaxRatesExceededException ex)
                    {
                        ShowFailedMessage(ex);
                    }
                    catch (Exception ex)
                    {
                        LogHelper.LogError(ex);
                        ShowFailedMessage("收藏失败，请重试");
                    }
                };
            addToStatusHandler.BeginInvoke(null, null);
        }

        protected void ForwardStatusHandler(object sender, RoutedEventArgs e)
        {
            Hyperlink link = sender as Hyperlink;
            mainWindow.IsOperatingOrignalStatus = link.CommandParameter.ToString() == "1";
            mainWindow.CurrentOperatingStatus = Rabbit.Utils.Common.GetListBoxItemFromChild(link.Parent as DependencyObject).Content as Status;
            mainWindow.tbOperationType.Text = "转发";
            mainWindow.chkCommentOrignalStatus.Visibility = System.Windows.Visibility.Visible;
            mainWindow.IsReplyToStatus = false;
            mainWindow.IsReplyToComment = false;
            mainWindow.popupReplyOrForward.PlacementTarget = (UIElement)link.Parent;
            mainWindow.popupReplyOrForward.Placement = System.Windows.Controls.Primitives.PlacementMode.Bottom;
            mainWindow.popupReplyOrForward.IsOpen = true;
        }
        #endregion`

        #region Show Large Image
        protected void statusImage_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            ImageEx img = sender as ImageEx;
            if (img != null)
            {
                PictureViewer pv = new PictureViewer();
                pv.PictureSource = img.LargerPictureSource;
                pv.ShowActivated = true;
                pv.Show();
            }
            e.Handled = true;
        }
        #endregion

        #region Popup User Information Helper

        protected void PopupUserInformation(User currentUser)
        {
            this.Dispatcher.BeginInvoke(new Action(() =>
            {
                (App.Current.MainWindow as MainWindow).CurrentUser = currentUser;
                (App.Current.MainWindow as MainWindow).popupUserInformation.IsOpen = true;
            }));
        }

        protected void UserHeadPicture_MouseEnter(object sender, MouseEventArgs e)
        {
            this.Dispatcher.BeginInvoke(new Action(() =>
            {
                (App.Current.MainWindow as MainWindow).popupUserInformation.PlacementTarget = sender as UIElement;
                if ((App.Current.MainWindow as MainWindow).popupUserInformation.IsOpen)
                {
                    (App.Current.MainWindow as MainWindow).popupUserInformation.IsOpen = false;
                }

                ListBoxItem item = Rabbit.Utils.Common.GetListBoxItemFromChild(sender as DependencyObject);

                if (item.Content.GetType() == typeof(Status))
                {
                    (App.Current.MainWindow as MainWindow).CurrentUser = (item.Content as Status).User;
                }
                else if (item.Content.GetType() == typeof(Comment))
                {
                    (App.Current.MainWindow as MainWindow).CurrentUser = (item.Content as Comment).User;
                }

                (App.Current.MainWindow as MainWindow).popupUserInformation.IsOpen = true;
            }), System.Windows.Threading.DispatcherPriority.Background);
        }

        protected void UserHeadPicture_MouseLeave(object sender, MouseEventArgs e)
        {
            this.Dispatcher.BeginInvoke(new Action(() =>
            {
                if (!(App.Current.MainWindow as MainWindow).popupUserInformation.IsMouseOver)
                {
                    (App.Current.MainWindow as MainWindow).popupUserInformation.IsOpen = false;
                }
            }), System.Windows.Threading.DispatcherPriority.Background);
        }
        #endregion

        #region Comments Operation Helper
        protected void ReplyToCommentsHandler(object sender, RoutedEventArgs e)
        {
            ListBoxItem item = Rabbit.Utils.Common.GetListBoxItemFromChild((sender as Hyperlink).Parent);
            Comment comment = item.Content as Comment;

            mainWindow.CurrentOperatingComment = comment;
            mainWindow.tbOperationType.Text = "回复";
            mainWindow.chkCommentOrignalStatus.Visibility = System.Windows.Visibility.Collapsed;
            mainWindow.IsReplyToComment = true;
            mainWindow.txtReplyOrForward.Text = "@" + comment.User.ScreenName + " ";
            mainWindow.popupReplyOrForward.PlacementTarget = (UIElement)((Hyperlink)sender).Parent;
            mainWindow.popupReplyOrForward.Placement = System.Windows.Controls.Primitives.PlacementMode.Bottom;
            mainWindow.popupReplyOrForward.IsOpen = true;
        }
        #endregion

        protected void menuCopyStatus_Click(object sender, RoutedEventArgs e)
        {
            string text = (sender as MenuItem).CommandParameter.ToString();
            Clipboard.SetText(text);
        }

        protected void OpenUserPage_Click(object sender, RoutedEventArgs e)
        {
            Rabbit.Utils.Common.OpenUserPage(long.Parse((sender as Hyperlink).CommandParameter.ToString()));
        }

        private void OpenUserBlog(object sender, RoutedEventArgs e)
        {
            Rabbit.Utils.Common.OpenUserPage((App.Current.MainWindow as MainWindow).CurrentUser.Id);
        }

        protected void OnUnHandledExceptionOccured(Exception ex)
        {
            ShowFailedMessage("获取数据错误");
        }

        protected void OnCallAPITooFrequentExceptionOccured(PublishAPICallTooFrequentException ex)
        {
            ShowFailedMessage("您操作太频繁了，休息会吧");
        }

        protected void TryPlaySound()
        {
            if (MySettings.IsPlayingSound.HasValue && MySettings.IsPlayingSound.Value)
            {
                Player.Play();
            }
        }

        protected void TryTwinkSystrayIcon(string message)
        {
            if (MySettings.IsTwinkleSysTrayIcon.HasValue && MySettings.IsTwinkleSysTrayIcon.Value)
            {
                App.TwinkleSysTrayIcon(message);
            }
        }

        protected void TryPopupMessage<T>(bool? IsPopup, Action<object, MouseButtonEventArgs> onMessageClicked,
          int MessageCount, string MessageType, T MessageObj)
        {

            NotifyMainWindowNewMessageCountChanged(MessageCount);
            TryTwinkSystrayIcon("微博有更新，点击查看");
            TryPlaySound();

            if (!IsPopup.HasValue)
            {
                return;
            }
            if (!IsPopup.Value)
            {
                return;
            }

            PopupdMessage popup = new PopupdMessage();
            popup.MessageClicked = onMessageClicked;
            popup.MessageCount = MessageCount;
            popup.MessageType = MessageType;

            string UserName = string.Empty;
            long UserID = 0;
            string UserPictureUrl = string.Empty;
            string Message = string.Empty;

            Type objType = typeof(T);
            if (objType == typeof(Status))
            {
                Status tempStatus = MessageObj as Status;
                UserName = tempStatus.User.ScreenName;
                UserID = tempStatus.User.Id;
                UserPictureUrl = tempStatus.User.ProfileImageUrl;
                Message = tempStatus.Text;
                Message += string.IsNullOrEmpty(tempStatus.InReplyToStatusText) ? ""
                    : Environment.NewLine + "//" 
                    + tempStatus.InReplyToScreenName 
                    + ":" 
                    + tempStatus.InReplyToStatusText;
            }
            else if (objType == typeof(Comment))
            {
                Comment tempStatus = MessageObj as Comment;
                UserName = tempStatus.User.ScreenName;
                UserID = tempStatus.User.Id;
                UserPictureUrl = tempStatus.User.ProfileImageUrl;
                Message = tempStatus.Text;
                Message += string.IsNullOrEmpty(tempStatus.InReplyToStatusText) ? ""
                    : Environment.NewLine + "//"
                    + tempStatus.InReplyToScreenName
                    + ":"
                    + tempStatus.InReplyToStatusText;
            }
            else if (objType == typeof(Letter))
            {
                Letter temp = MessageObj as Letter;
                UserName = temp.SenderScreenName;
                UserID = temp.SenderId;
                UserPictureUrl = temp.Sender.ProfileImageUrl;
                Message = temp.Text;
            }
            popup.UserName = UserName;
            popup.UserID = UserID;
            popup.UserPictureUrl = UserPictureUrl;
            popup.Message = Message;
            popup.Show();
        }

        //TODO this need to be refactored later to make good use of principle of OOP
        public abstract void pager_OnFirstPageClick(object sender, System.Windows.RoutedEventArgs e);
        public abstract void pager_OnPreviousePage(object sender, System.Windows.RoutedEventArgs e);
        public abstract void pager_OnNextPageClick(object sender, System.Windows.RoutedEventArgs e);
    }
}
